import 'dart:convert';

import 'package:baidu_map_plugin/baidu_map.dart';
import 'package:baidu_map_plugin/widgets/native/base_platfrom_view.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

typedef PlatformViewCreatedCallback = void Function(
    BaiDuMapViewPlatformViewController controller);
mixin NativeCallHandler {
  void onSelectedOverlay(OverlayOption option);
}

class BaiDuMapViewPlatformView
    extends BasePlatformView<BaiDuMapViewPlatformViewController>
    with NativeCallHandler {
  final Function(OverlayOption) selectedOverlay;

  BaiDuMapViewPlatformView({
    Key key,
    PlatformViewCreatedCallback platformViewCreatedCallback,
    FlutterNativeBaiDuViewModel creationParams,
    this.selectedOverlay,
  }) : super(
          key: key,
          onPlatformViewCreatedCallback: platformViewCreatedCallback,
          creationParams: creationParams,
        );

  @override
  initState() {
    super.initState();
  }

  @override
  String viewType() {
    return 'plugins.baidumapplugin_example/mapview';
  }

  @override
  BaiDuMapViewPlatformViewController createPlatformViewController(
      String viewType, int id) {
    return BaiDuMapViewPlatformViewController(this, viewType, id);
  }

  @override
  void onSelectedOverlay(OverlayOption option) {
    selectedOverlay?.call(option);
  }
}

class BaiDuMapViewPlatformViewController extends BasePlatformViewController {
  final NativeCallHandler nativeCallHandler;

  BaiDuMapViewPlatformViewController(
      this.nativeCallHandler, String viewType, int id)
      : super(viewType, id) {
    _setMethodCallHandler();
  }

  void updateMapView(FlutterNativeBaiDuViewModel flutterNativeBaiDuViewModel) {
    nativePlatformViewChannel.invokeMethod(
        "updateMapView", jsonEncode(flutterNativeBaiDuViewModel));
  }

  void setMapViewCenter(double latitude, double longitude) {
    nativePlatformViewChannel.invokeMethod(
      "setMapViewCenter",
      {
        "latitude": latitude ?? 0.0,
        "longitude": longitude ?? 0.0,
      },
    );
  }

  void _setMethodCallHandler() {
    nativePlatformViewChannel.setMethodCallHandler(_onMethodCall);
  }

  Future<void> _onMethodCall(MethodCall call) {
    switch (call.method) {
      case 'onSelectedOverlay':
        if (call.arguments != null) {
          nativeCallHandler.onSelectedOverlay(
              OverlayOption.fromJson(jsonDecode(call.arguments)));
        }
        break;
      default:
        throw UnimplementedError(
            "${call.method} was invoked but isn't implemented by PlatformViewsService");
    }
    return null;
  }
}
